<?php

define('DS', DIRECTORY_SEPARATOR);

require __DIR__  . DS . 'sync_socket_lib.php';


/**
 * @param      $host
 * @param      $port
 * @param      $method
 * @param      $data
 * @param      $socket
 * @param bool $noBlocking
 * @return bool|false|string
 */
function syncCheckClient($host, $port, $method, $data, &$socket, $noBlocking = true)
{

    $client = new SyncTcpClient();
    $client->connection($host, $port);
    fwrite(STDOUT, "\nconnect to server: [{$host}:{$port}]...\n");

    $message = json_encode([
        "method" => $method,
        "data" => $data
    ]);

    fwrite(STDOUT, "send to server: $message\n");
    $len = $client->send($message);
    if ($len === 0) {
        fwrite(STDOUT, "socket closed\n");
        return false;
    }

    if ($noBlocking) {
        // 非阻塞方式, 不等结果，之间返回调用成功
        return true;
    } else {
        // 阻塞方式，等待响应，读取后返回
        $msg = $client->receive( 4096);
        if ($msg) {
            fwrite(STDOUT, "receive server: $msg\n");
            // 获取到返回结果后，再返回
            return json_decode($msg, true);
        } else {
            fwrite(STDOUT, "socket closed\n");
            return false;
        }
        return true;
    }
}

/**
 * 发起请求
 *
 * @param integer   $productId   产品ID
 * @param resource  $socket     套接字
 * @param bool      $noBlocking      阻塞与否
 *
 * @return bool|false|string
 */
function syncCheckInventory($productId, &$socket, $noBlocking = true)
{
    // client.php
    $host = "127.0.0.1";
    $port = 8081;

    $data = array('productId' => $productId);

    return syncCheckClient($host, $port, 'inventory', $data, $socket, $noBlocking);
}

/**
 * 检查产品可售
 *
 * @param      $productId
 * @param      $socket
 * @param bool $noBlocking
 * @return bool|false|string
 */
function syncCheckProduct($productId, &$socket, $noBlocking = true)
{
    // client.php
    $host = "127.0.0.1";
    $port = 8082;

    $data = array('productId' => $productId);

    return syncCheckClient($host, $port, 'product', $data, $socket, $noBlocking);
}

/**
 * 检查促销信息
 *
 * @param      $productId
 * @param      $socket
 * @param bool $noBlocking
 * @return bool|false|string
 */
function syncCheckPromo($productId, &$socket, $noBlocking = true)
{
    // client.php
    $host = "127.0.0.1";
    $port = 8083;

    $data = array('productId' => $productId);

    return syncCheckClient($host, $port, 'promo', $data, $socket, $noBlocking);
}

/**
 * 响应来自客户加购请求
 *
 * @param $socket
 * @param $method
 * @param $productId
 * @param $re
 * @return bool
 */
function syncResponseClient($socket, $productId, $re)
{
    global $clients;
    $reMsg = array('method' => 'cart', 'data' => array('product_id' => $productId), 're' => $re, 'msg' => 'suc');
    $data = json_encode($reMsg);
    // 这里响应了，发起 加购 请求的客户端，
    fwrite($socket, $data);
    $key = array_search($socket, $clients);
    // 关闭连接，
    fclose($socket);
    // 响应客户端后，就把它的socket从 select 去移除
    unset($clients[$key]);
    return true;
}

$host = '0.0.0.0';
$port = 8080;

$server = new SyncTcpServer($host, $port);

$server->on('accept', function(SyncTcpServer $server, $socket, $info) {
    $server->console('accept a new client~' . PHP_EOL);
});

$server->on('receive', function(SyncTcpServer $server, $socket, $info, $data) {
    $server->console('received data :' . $data . ' from : ' . strval($socket) . PHP_EOL);

    // 业务
    $dataArr = json_decode($data, true);
    $method = $dataArr["method"];
    $noBlocking = boolval($dataArr['noBlocking']);
    $productId = $dataArr['data']['productId'];

    $noBlocking = false;

    $checkAllSuc = false;
    $inventorySocket = $productSocket = $promoSocket = null;
    // 依次发起三个检查请求
    $requestInventorySuc = syncCheckInventory($productId, $inventorySocket, $noBlocking);
    if ($requestInventorySuc) {
        if ($requestInventorySuc['data']['re']) {

            $requestProductSuc = syncCheckProduct($productId, $productSocket, $noBlocking);
            if ($requestProductSuc) {
                if ($requestProductSuc['data']['re']) {

                    $requestPromoSuc = syncCheckPromo($productId, $promoSocket, $noBlocking);
                    if (isset($requestPromoSuc['data']['re'])) {
                        $checkAllSuc = true;
                    }
                }
            }
        }
        // 如果检查库存失败，后面流程就不用继续了
    }

    $reMsg = array('method' => 'cart', 'data' => array('product_id' => $productId), 're' => $checkAllSuc, 'msg' => 'suc');
    $reData = json_encode($reMsg);
    fwrite($socket, $reData . PHP_EOL);
    $server->console( 'response request: ' . strval($socket) . ' , data: ' . $reData . PHP_EOL . PHP_EOL);
    // 响应客户端后，关闭连接，并把它的socket从 select 去移除
    $server->close($socket);
});

$server->on('close', function(SyncTcpServer $server, $socket, $info) {
    $server->console('client :' . strval($socket) . ' closed.' . PHP_EOL);
});

$server->run();